\documentclass[twoside,a4paper]{article}
\usepackage{geometry}
\geometry{margin=1.5cm, vmargin={0pt,1cm}}
\setlength{\topmargin}{-1cm}
\setlength{\paperheight}{29.7cm}
\setlength{\textheight}{25.3cm}


% useful packages.
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{enumerate}
\usepackage{graphicx}
\usepackage{multicol}
\usepackage{fancyhdr}
\usepackage{layout}
\usepackage{ctex}%引入中文包
\usepackage{graphicx}
\usepackage{subfigure}
\usepackage{float}



\usepackage{listings}
\usepackage{xcolor}      %代码着色宏包
\usepackage{CJK}         %显示中文宏包

\definecolor{mygreen}{rgb}{0,0.6,0}
\definecolor{mygray}{rgb}{0.5,0.5,0.5}
\definecolor{mymauve}{rgb}{0.58,0,0.82}
\lstset{
 backgroundcolor=\color{lightgray}, 
 basicstyle = \footnotesize,       
 breakatwhitespace = false,        
 breaklines = true,                 
 captionpos = b,                    
 commentstyle = \color{mygreen}\bfseries,
 extendedchars = false,             
 frame =shadowbox, 
 framerule=0.5pt,
 keepspaces=true,
 keywordstyle=\color{blue}\bfseries, % keyword style
 language = C++,                     % the language of code
 otherkeywords={string}, 
 numbers=left, 
 numbersep=5pt,
 numberstyle=\tiny\color{mygray},
 rulecolor=\color{black},         
 showspaces=false,  
 showstringspaces=false, 
 showtabs=false,    
 stepnumber=1,         
 stringstyle=\color{mymauve},        % string literal style
 tabsize=2,          
 title=\lstname                      
}


% some common command
\newcommand{\dif}{\mathrm{d}}
\newcommand{\avg}[1]{\left\langle #1 \right\rangle}
\newcommand{\difFrac}[2]{\frac{\dif #1}{\dif #2}}
\newcommand{\pdfFrac}[2]{\frac{\partial #1}{\partial #2}}
\newcommand{\OFL}{\mathrm{OFL}}
\newcommand{\UFL}{\mathrm{UFL}}
\newcommand{\fl}{\mathrm{fl}}
\newcommand{\op}{\odot}
\newcommand{\Eabs}{E_{\mathrm{abs}}}
\newcommand{\Erel}{E_{\mathrm{rel}}}

\begin{document}

\pagestyle{fancy}
\fancyhead{}
\lhead{方丹吟 3190102758}
\chead{五则运算计算器的实现}
\rhead{2022.12.22}

\begin{center}
    \LARGE\songti\textbf{五则运算计算器的实现} \\%标题
    \large\kaishu\textbf{方丹吟\qquad 3190102758}%一般是我的姓名
\end{center}


\section*{一、设计思路}
\subsection*{1.将中缀表达式转为后缀表达式}
\begin{enumerate}
\item 建立一个操作符栈 \textbf{ops}，用以临时存放操作符；同时建立一个数组\textbf{suffix}用以存放后缀表达式；
\item 从左到右读取中缀表达式，如果是运算数，直接插入到后缀表达式\textbf{suffix}的最后；

\begin{itemize}
\item 首先判断当前字符是不是（带正负号的）数，如果是，则从当前字符开始切片，直到出现操作符之前为止，将切片的字符串转化为double型的运算数加入到后缀表达式中，这种方法的好处是可以方便地识别浮点数；
\item 如果正负号不是运算符，而是数的一部分，则正负号出现在字符的第一个位置，或者正负号前面是左括号；
\end{itemize}

\item 如果是运算符，就把其优先级和操作符栈顶操作符优先级比较：
\begin{itemize}
\item 如果当前运算符优先级大于栈顶操作符优先级，则运算符直接入栈\textbf{ops}；
\item 如果当前运算符优先级小于等于栈顶操作符，则不断将栈顶操作符弹出放入后缀表达式中，直到当前运算符优先级大于栈顶操作符优先级，然后运算符入栈\textbf{ops}；
\end{itemize}

\item 如果是括号：

\begin{itemize}
\item 如果是左括号，则直接压入操作符栈\textbf{ops}；
\item 如果是右括号，不断从操作符栈中弹出操作符放入后缀表达式\textbf{suffix}，直到栈顶元素为左括号，然后删除左括号；
\end{itemize}

\item 中缀表达式扫描完毕后，如果操作符栈\textbf{ops}中仍然有元素，则依次弹出放到后缀表达式\textbf{suffix}中
\end{enumerate}




\subsection*{2.后缀表达式的计算}
\begin{enumerate}
\item 建立一个栈\textbf{mystack}用于临时存放运算数和中间计算结果；
\item 从左到右扫描后缀表达式\textbf{suffix}，如果是运算数，则压入栈\textbf{mystack}；
\item 如果是运算符，则从栈\textbf{mystack}中依次弹出两个数，第一个弹出的\textbf{secondnum}是加数/减数/乘数/除数/指数，第二个弹出的\textbf{firstnum}是被加数/被减数/被乘数/被除数/底数。根据运算符对这两个数进行运算，并将运算结果压入栈；
\item 当后缀表达式扫描完毕时，栈中只剩一个元素，即为运算的结果；
\end{enumerate} 


\subsection*{3.输入表达式的检查}
\begin{enumerate}
\item 出现非数字型字符且不是“+-*/\^{}.”中的任何一个，说明输入中含有非法字符，终止程序并报错"Please check your input! Invalid characters exist in the expression"；
\item 小数点前后不是数字，终止程序并报错"Please check you input! There may be a problem with the decimal point"；
\item 左右括号数量不同,终止程序并报错"Please check your input! The number of right brackts is expected to equal to the left."
\item 在计算后置表达式时发现运算符时“/”且\textbf{secondnum}=0，说明除数为零，终止程序并报错"Error: divide by zero!"
\end{enumerate}

\section*{二、测试说明}
在main()函数中定义运算符优先级：（乘方>乘除>加减），将输入的中缀表达式进行检验，确认输入无误后转成后缀表达式进行计算。以下例子对浮点数、带括号的五则运算进行了测试，验证该程序可以正确计算；同时对表达式逻辑错误、除数为0的情况进行了测试，验证该程序可以检测错误输入并给出错误信息；
\begin{itemize}
\item \textbf{Input 1}: 2ˆ(1 + 3) - 5 ∗ (15.23)/(1 + 2) ∗ 3 - 5
\item \textbf{Input 2}: 1.25 + (3 ∗ (1 + 2ˆ2) ∗ 3 - 43)ˆ(4 - 2)
\item \textbf{Input 3}: 2ˆ(1 + 3)) - 5 ∗ (15.23)/(1 + 2) ∗ 3 - 5
\item \textbf{Input 4}: 2ˆ(1 + 3) - 5 ∗ (15.23)/(1 - 1) ∗ 3 - 5
\item \textbf{Input 5}: 2ˆ(1 + 3) - 5 ∗ (15..23)/(1 + 2) ∗ 3 - 5
\item \textbf{Input 6}: 2ˆ(1 + a3) - 5 ∗ (15.23)/(1 + 2) ∗ 3 - 5
\end{itemize}

\section*{三、测试结果}

\begin{figure}[H]
    \centering
     \includegraphics{output1}
     \caption{Output 1: 测试五则运算}
\end{figure}

\begin{figure}[H]
    \centering
     \includegraphics{output2}
     \caption{Output 2: 测试五则运算}
\end{figure}

\begin{figure}[H]
    \centering
     \includegraphics{output3}
     \caption{Output 3: 测试错误括号不匹配}
\end{figure}

\begin{figure}[H]
    \centering
     \includegraphics{output4}
     \caption{Output 4: 测试错误除数为零}
\end{figure}

\begin{figure}[H]
    \centering
     \includegraphics{output5}
     \caption{Output 5: 测试错误数字中有多个小数点}
\end{figure}

\begin{figure}[H]
    \centering
     \includegraphics{output6}
     \caption{Output 6: 测试错误非法字符}
\end{figure}

\end{document}

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: t
%%% End: 
